#pragma once

#include <vex/core/make_raw_handle.h>
#include <vex/core/unique_ptr_support.h>

namespace vex {
    namespace core {
        using implementation::handle_from_base;

#ifdef VEX_HAS_CPP_11_FEATURE_SET_3
        template < class TBase, class ...TArgs >
        std::unique_ptr<TBase, unique_delete> make_unique_handle(TArgs&& ...p_args)
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>(std::forward<TArgs>(p_args)...));
        }
#else
        template < class TBase>
        std::unique_ptr<TBase, unique_delete> make_unique_handle()
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>());
        }

        template <class TBase, class TArg1>
        std::unique_ptr<TBase, unique_delete> make_unique_handle(
            TArg1&& p_arg1)
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>(
                std::forward<TArg1>(p_arg1)));
        }

        template <class TBase, class TArg1, class TArg2>
        std::unique_ptr<TBase, unique_delete> make_unique_handle(
            TArg1 && p_arg1, TArg2 && p_arg2) 
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>(
                std::forward<TArg1>(p_arg1), 
                std::forward<TArg2>(p_arg2)));
        }

        template <class TBase, class TArg1, class TArg2, class TArg3>
        std::unique_ptr<TBase, unique_delete> make_unique_handle(
            TArg1 && p_arg1, TArg2 && p_arg2, TArg3 && p_arg3) 
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>( 
                std::forward<TArg1>(p_arg1), 
                std::forward<TArg2>(p_arg2), 
                std::forward<TArg3>(p_arg3))); 
        }

        template <class TBase, class TArg1, class TArg2, class TArg3, class TArg4>
        std::unique_ptr<TBase, unique_delete> make_unique_handle(
            TArg1 && p_arg1, TArg2 && p_arg2, TArg3 && p_arg3, TArg4 && p_arg4) 
        {
            return std::unique_ptr<TBase, unique_delete>(
                make_raw_handle_ext<TBase, vex::unique>(
                std::forward<TArg1>(p_arg1), 
                std::forward<TArg2>(p_arg2), 
                std::forward<TArg3>(p_arg3), 
                std::forward<TArg4>(p_arg4))); 
        }
#endif
    }

    using core::make_unique_handle;
}